home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / NPC_soldier.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-27  |  26.1 KB  |  1,024 lines

  1. /*
  2. ==============================================================================
  3.  
  4. soldier NPC
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. #include "g_local.h"
  10. #include "npc_soldier.h"
  11.  
  12.  
  13. static int sound_pain;
  14. static int sound_die;
  15. static int sound_idle;
  16. static int sound_talk;
  17. static int sound_talk2;
  18. static int sound_sight;
  19. static int sound_search;
  20. static int sound_help;
  21. static int sound_please;
  22. static int sound_groan;
  23. static int sound_ctalk;
  24. static int sound_csight;
  25. static int sound_shoot;
  26. static int sound_shoot2;
  27. static int sound_step1;
  28. static int sound_step2;
  29. int kick = 0;
  30.  
  31. void soldier_standstill (edict_t *self);
  32. void soldier_fidget (edict_t *self);
  33. void soldier_talk (edict_t *self);
  34. void soldier_cower (edict_t *self);
  35. void soldier_run (edict_t *self);
  36. void soldier_pain (edict_t *self, edict_t *other, float kick, int damage);
  37.  
  38. void soldier_search (edict_t *self)
  39. {
  40.     gi.sound (self, CHAN_VOICE, sound_search, 1, ATTN_NORM, 0);
  41. }
  42.  
  43. mframe_t soldier_frames_stand [] =
  44. {
  45.     ai_stand, 0, NULL,
  46.     ai_stand, 0, NULL,
  47.     ai_stand, 0, NULL,
  48.     ai_stand, 0, NULL,
  49.     ai_stand, 0, NULL,    
  50.     ai_stand, 0, NULL,
  51.     ai_stand, 0, NULL,
  52.     ai_stand, 0, NULL,
  53.     ai_stand, 0, NULL
  54.     
  55. };
  56. mmove_t soldier_move_stand = {FRAME_stand01, FRAME_stand09, soldier_frames_stand, NULL};
  57.  
  58. void soldier_stand (edict_t *self)
  59. {
  60.     self->monsterinfo.currentmove = &soldier_move_stand;
  61. }
  62.  
  63. mframe_t soldier_frames_fidget [] =
  64. {
  65.     ai_move, 0, NULL,
  66.     ai_move, 0, NULL,
  67.     ai_move, 0, NULL,
  68.     ai_move, 0, NULL,
  69.     ai_move, 0, NULL,
  70.     ai_move, 0, NULL,    
  71.     ai_move, 0, NULL,
  72.     ai_move, 0, NULL,
  73.     ai_move, 0, NULL,
  74.     ai_move, 0, NULL,
  75.     ai_move, 0, NULL,    
  76.     ai_move, 0, NULL,
  77.     ai_move, 0, NULL,
  78.     ai_move, 0, NULL,
  79.     ai_move, 0, NULL
  80.     
  81. };
  82. mmove_t soldier_move_fidget = {FRAME_fid01, FRAME_fid14, soldier_frames_fidget, soldier_standstill};
  83.  
  84. void soldier_fidget (edict_t *self)
  85. {
  86.  
  87.     if (random() > 0.15)
  88.         return;
  89.  
  90.     self->monsterinfo.currentmove = &soldier_move_fidget;
  91.     
  92. }
  93.  
  94. mframe_t soldier_frames_still [] =
  95. {
  96.     ai_move, 0, soldier_fidget,
  97.     ai_move, 0, NULL,
  98.     ai_move, 0, NULL,
  99.     ai_move, 0, NULL,
  100.     ai_move, 0, NULL,
  101.     ai_move, 0, NULL,    
  102.     ai_move, 0, NULL,
  103.     ai_move, 0, NULL,
  104.     ai_move, 0, NULL,
  105.     ai_move, 0, NULL
  106.     
  107. };
  108. mmove_t soldier_move_standstill = {FRAME_stand01, FRAME_stand09, soldier_frames_still, soldier_standstill};
  109.  
  110. void soldier_standstill (edict_t *self)
  111. {
  112.     self->pain = soldier_pain; 
  113.     self->monsterinfo.melee = soldier_standstill;
  114.     self->monsterinfo.currentmove = &soldier_move_standstill;
  115. }
  116. void soldier_step1 (edict_t *self)
  117. {
  118.     gi.sound (self, CHAN_VOICE, sound_step1, 1, ATTN_NORM, 0);
  119. }
  120. void soldier_step2 (edict_t *self)
  121. {
  122.     gi.sound (self, CHAN_VOICE, sound_step2, 1, ATTN_NORM, 0);
  123. }
  124. mframe_t soldier_frames_walk [] =
  125. {
  126.     ai_run, 0.0, NULL,
  127.     ai_run, 3.3, NULL,
  128.     ai_run, 8.9, NULL,
  129.     ai_run, 10.0, NULL,
  130.     ai_run, 0.0, soldier_step1,
  131.     ai_run, 0.0, NULL,
  132.     ai_run, 0.0, NULL,
  133.     ai_run, 3.0, NULL,
  134.     ai_run, 8.0, NULL,
  135.     ai_run, 10.0, NULL,
  136.     ai_run, 0.0, soldier_step2,
  137.     ai_run, 0.0, NULL
  138. };
  139. mmove_t soldier_move_walk = {FRAME_walk01, FRAME_walk12, soldier_frames_walk, NULL};
  140.  
  141. mframe_t soldier_frames_walking [] =
  142. {
  143.     ai_run, 0.0, NULL,
  144.     ai_run, 3.3, NULL,
  145.     ai_run, 8.9, NULL,
  146.     ai_run, 10.0, NULL,
  147.     ai_run, 0.0, soldier_step1,
  148.     ai_run, 0.0, NULL,
  149.     ai_run, 0.0, NULL,
  150.     ai_run, 3.0, NULL,
  151.     ai_run, 8.0, NULL,
  152.     ai_run, 10.0, NULL,
  153.     ai_run, 0.0, soldier_step2,
  154.     ai_run, 0.0, NULL
  155. };
  156. mmove_t soldier_move_walking = {FRAME_walk01, FRAME_walk12, soldier_frames_walking, NULL};
  157.  
  158. void soldier_walk (edict_t *self)
  159. {
  160.     self->monsterinfo.currentmove = &soldier_move_walk;
  161. }
  162.  
  163. void soldier_walking (edict_t *self)
  164. {
  165.     self->monsterinfo.currentmove = &soldier_move_walking;
  166. }
  167.  
  168. //This for a soldier you want to stay active, but not running
  169. mframe_t soldier_frames_standby [] =
  170. {
  171.     ai_run, 0.0, NULL,
  172.     ai_run, 0.0, NULL,
  173.     ai_run, 0.0, NULL,
  174.     ai_run, 0.0, NULL,
  175.     ai_run, 0.0, NULL,
  176.     ai_run, 0.0, NULL,
  177.     ai_run, 0.0, NULL,
  178.     ai_run, 0.0, NULL,
  179.     ai_run, 0.0, NULL
  180. };
  181. mmove_t soldier_move_standby = {FRAME_stand01, FRAME_stand09, soldier_frames_standby, soldier_run};
  182.  
  183. void soldier_standby (edict_t *self)
  184. {
  185.     self->monsterinfo.currentmove = &soldier_move_standby;
  186. }
  187.  
  188. mframe_t soldier_frames_run1 [] =
  189. {
  190.     ai_run, 25, NULL,
  191.     ai_run, 10, NULL,
  192.     ai_run, 5, soldier_step1,
  193.     ai_run, 24, NULL,
  194.     ai_run, 11, NULL,
  195.     ai_run, 5, soldier_step2
  196. };
  197. mmove_t soldier_move_run1 = {FRAME_run01, FRAME_run06, soldier_frames_run1, NULL};
  198.  
  199. void soldier_run (edict_t *self)
  200. {
  201.     if ((self->monsterinfo.aiflags & AI_STAND_GROUND))
  202.         self->monsterinfo.currentmove = &soldier_move_stand;
  203.     else
  204.         self->monsterinfo.currentmove = &soldier_move_run1;
  205. }
  206.  
  207. void soldierTalk (edict_t *self)
  208. {
  209.     if (self->spawnflags & 1)
  210.         gi.sound(self, CHAN_VOICE, sound_talk2, 1, ATTN_IDLE, 0);
  211.     else if (!Q_stricmp(self->classname, "npc_commander"))
  212.         gi.sound (self, CHAN_VOICE, sound_ctalk, 1, ATTN_IDLE, 0);
  213.     else
  214.         gi.sound (self, CHAN_VOICE, sound_talk, 1, ATTN_IDLE, 0);
  215. }
  216.  
  217. void soldierhelp (edict_t *self)
  218. {
  219.     gi.sound (self, CHAN_VOICE, sound_help, 1, ATTN_IDLE, 0);
  220. }
  221.  
  222. void soldiergroan (edict_t *self)
  223. {
  224.     if (random() > 0.15)
  225.         return;
  226.     if (random() > 0.5)
  227.         gi.sound (self, CHAN_VOICE, sound_groan, 1, ATTN_IDLE, 0);
  228.     else
  229.         gi.sound (self, CHAN_VOICE, sound_help, 1, ATTN_IDLE, 0);
  230. }
  231.  
  232. void mouth_open (edict_t *self)
  233. {
  234.     self->s.skinnum = 1;
  235. }
  236.  
  237. void mouth_close (edict_t *self)
  238. {
  239.     self->s.skinnum = 0;
  240. }
  241.  
  242. mframe_t soldier_frames_talk [] =
  243. {
  244.     ai_charge, 0, NULL,
  245.     ai_charge, 0, NULL,
  246.     ai_charge, 0, NULL,
  247.     ai_charge, 0, NULL,
  248.     ai_charge, 0, NULL,
  249.     ai_charge, 0, NULL,
  250.     ai_charge, 0, NULL,
  251.     ai_charge, 0, NULL,
  252.     ai_charge, 0, NULL,
  253.     ai_charge, 0, NULL,
  254.     ai_charge, 0, NULL,
  255.     ai_charge, 0, NULL,
  256.     ai_charge, 0, NULL,
  257.     ai_charge, 0, NULL,
  258.     ai_charge, 0, NULL,
  259.     ai_charge, 0, NULL,
  260.     ai_charge, 0, NULL,
  261.     ai_charge, 0, NULL
  262. };
  263. mmove_t soldier_move_talk = {FRAME_talk01, FRAME_talk18, soldier_frames_talk, soldier_standstill};
  264.  
  265. mframe_t soldier_frames_talkstart [] =
  266. {
  267.     ai_charge, 0, soldierTalk,
  268.     ai_charge, 0, NULL,
  269.     ai_charge, 0, NULL,
  270.     ai_charge, 0, NULL,
  271.     ai_charge, 0, NULL,
  272.     ai_charge, 0, NULL,
  273.     ai_charge, 0, NULL,
  274.     ai_charge, 0, NULL,
  275.     ai_charge, 0, NULL
  276. };
  277. mmove_t soldier_move_talkstart = {FRAME_stand01, FRAME_stand09, soldier_frames_talkstart, soldier_talk};
  278.  
  279. mframe_t soldier_frames_signal [] =
  280. {
  281.     ai_move, 0, NULL,
  282.     ai_move, 0, NULL,
  283.     ai_move, 0, NULL,
  284.     ai_move, 0, NULL,
  285.     ai_move, 0, NULL,
  286.     ai_move, 0, NULL,
  287.     ai_move, 0, NULL,
  288.     ai_move, 0, NULL,
  289.     ai_move, 0, NULL
  290. };
  291.     
  292. mmove_t soldier_move_signal = {FRAME_signal01, FRAME_signal09, soldier_frames_signal, soldier_run};
  293.  
  294. mframe_t soldier_frames_comtalk3 [] =
  295. {
  296.     ai_stand, 0, mouth_open,
  297.     ai_stand, 0, mouth_close,
  298.     ai_stand, 0, mouth_open,
  299.     ai_stand, 0, mouth_close,
  300.     ai_stand, 0, mouth_open,
  301.     ai_stand, 0, mouth_close,
  302.     ai_stand, 0, mouth_open,
  303.     ai_stand, 0, mouth_close,
  304.     ai_stand, 0, NULL
  305. };
  306.     
  307. mmove_t soldier_move_comtalk3 = {FRAME_stand01, FRAME_stand09, soldier_frames_comtalk3, soldier_standstill};
  308.  
  309. void soldier_comtalk3 (edict_t *self)
  310. {
  311.         self->monsterinfo.currentmove = &soldier_move_comtalk3;
  312. }
  313. mframe_t soldier_frames_comtalk2 [] =
  314. {
  315.     ai_stand, 0, mouth_open,
  316.     ai_stand, 0, mouth_close,
  317.     ai_stand, 0, mouth_open,
  318.     ai_stand, 0, mouth_close,
  319.     ai_stand, 0, mouth_open,
  320.     ai_stand, 0, mouth_close,
  321.     ai_stand, 0, mouth_open,
  322.     ai_stand, 0, mouth_close,
  323.     ai_stand, 0, NULL
  324. };
  325.     
  326. mmove_t soldier_move_comtalk2 = {FRAME_stand01, FRAME_stand09, soldier_frames_comtalk2, soldier_comtalk3};
  327.  
  328. void soldier_comtalk2 (edict_t *self)
  329. {
  330.     self->monsterinfo.currentmove = &soldier_move_comtalk2;
  331. }
  332.  
  333. mframe_t soldier_frames_comtalk [] =
  334. {
  335.     ai_stand, 0, mouth_open,
  336.     ai_stand, 0, mouth_close,
  337.     ai_stand, 0, mouth_open,
  338.     ai_stand, 0, mouth_close,
  339.     ai_stand, 0, mouth_open,
  340.     ai_stand, 0, mouth_close,
  341.     ai_stand, 0, mouth_open,
  342.     ai_stand, 0, mouth_close,
  343.     ai_stand, 0, NULL
  344. };
  345.     
  346. mmove_t soldier_move_comtalk = {FRAME_signal01, FRAME_signal09, soldier_frames_comtalk, soldier_comtalk2};
  347.  
  348. mframe_t soldier_frames_cower [] =
  349. {
  350.     ai_move, 0, NULL,
  351.     ai_move, 0, NULL,
  352.     ai_move, 0, NULL,
  353.     ai_move, 0, soldiergroan,
  354.     ai_move, 0, NULL,
  355.     ai_move, 0, NULL,
  356.     ai_move, 0, NULL,
  357.     ai_move, 0, NULL,
  358.     ai_move, 0, NULL,
  359.     ai_move, 0, NULL,
  360.     ai_move, 0, NULL,
  361.     ai_move, 0, NULL,
  362.     ai_move, 0, NULL,
  363.     ai_move, 0, NULL,
  364.     ai_move, 0, NULL,
  365.     ai_move, 0, NULL,
  366.     ai_move, 0, NULL,
  367.     ai_move, 0, NULL,
  368.     ai_move, 0, NULL,
  369.     ai_move, 0, NULL,
  370.     ai_move, 0, NULL
  371. };
  372.     
  373. mmove_t soldier_move_cower = {FRAME_cower01, FRAME_cower21, soldier_frames_cower, soldier_cower};
  374.  
  375. void soldier_cower (edict_t *self)
  376. {
  377.     self->monsterinfo.currentmove = &soldier_move_cower;
  378. }
  379.  
  380. mframe_t soldier_frames_fall [] =
  381. {
  382. /*
  383.     ai_stand, 0, ai_still,
  384.     ai_stand, 0, soldierhelp,
  385.     ai_stand, 0, ai_still,
  386.     ai_stand, 0, ai_still,
  387.     ai_stand, 0, ai_still
  388. */
  389. // Vic
  390.     ai_move, 0, NULL,
  391.     ai_move, 0, soldierhelp,
  392.     ai_move, 0, NULL,
  393.     ai_move, 0, NULL,
  394.     ai_move, 0, NULL
  395. };
  396.     
  397. mmove_t soldier_move_fall = {FRAME_fall01, FRAME_fall05, soldier_frames_fall, soldier_cower};
  398.  
  399. void soldier_fall (edict_t *self)
  400. {
  401.     self->monsterinfo.currentmove = &soldier_move_fall;
  402. }
  403.  
  404. void soldier_sight (edict_t *self, edict_t *other)
  405. {
  406.     if (self->spawnflags & 1)
  407.         self->monsterinfo.currentmove = &soldier_move_run1;
  408.     else if (self->spawnflags & 8)
  409.         self->monsterinfo.currentmove = &soldier_move_run1;
  410.     else
  411.     {
  412.         if (!Q_stricmp(self->classname, "npc_commander"))
  413.             gi.sound (self, CHAN_AUTO, sound_csight, 1, ATTN_NORM, 0);
  414.         else
  415.             gi.sound (self, CHAN_AUTO, sound_sight, 1, ATTN_NORM, 0);
  416.         self->monsterinfo.currentmove = &soldier_move_signal;
  417.     }
  418. }
  419. void Soldier_machgun (edict_t *self)
  420. {
  421.     vec3_t    forward, right;
  422.     vec3_t    start;
  423.     vec3_t    end;
  424.     vec3_t    dir;
  425.     int        flash_number = MZ2_TANK_BLASTER_3;
  426.     int        damage = 15;
  427.     
  428.     kick = kick + 1;
  429.     if(kick > 6)
  430.         kick = 1;
  431.  
  432.     AngleVectors (self->s.angles, forward, right, NULL);
  433.     
  434.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  435.     VectorCopy (self->s.origin, start);
  436.     right[0] = right[0] * (12 + kick);
  437.     right[1] = right[1] * (12 + kick);
  438.     VectorAdd(start, right, start);
  439.     start[2] += (36 + kick);
  440.     forward[0] = forward[0] * 32;
  441.     forward[1] = forward[1] * 32;
  442.     VectorAdd(start, forward, start);
  443.     VectorCopy (self->enemy->s.origin, end);
  444.     end[2] += self->enemy->viewheight;
  445.     VectorSubtract (end, start, dir);
  446.  
  447.     gi.sound (self, CHAN_VOICE, sound_shoot2, 1, ATTN_NORM, 0);
  448.     
  449.     gi.WriteByte (svc_temp_entity);
  450.     gi.WriteByte (TE_BLASTER_MUZZLEFLASH);
  451.     gi.WritePosition (start);
  452.     gi.multicast (start, MULTICAST_PHS);
  453.     
  454.     monster_fire_bullet (self, start, dir, 5, 1, 20, 20, flash_number);
  455. }
  456.  
  457. void Soldier_Shot (edict_t *self)
  458. {
  459.     
  460.     vec3_t    forward, right;
  461.     vec3_t    start;
  462.     vec3_t    end;
  463.     vec3_t    dir;
  464.     vec3_t    from;
  465.     trace_t tr;
  466.     int        flash_number = MZ2_TANK_BLASTER_3;
  467.     int        damage = 15;
  468.  
  469.     AngleVectors (self->s.angles, forward, right, NULL);
  470.     
  471.     G_ProjectSource (self->s.origin, monster_flash_offset[flash_number], forward, right, start);
  472.     VectorCopy (self->s.origin, start);
  473.     right[0] = right[0] * 8;
  474.     right[1] = right[1] * 8;
  475.     VectorAdd(start, right, start);
  476.     start[2] += 28;
  477.     forward[0] = forward[0] * 26;
  478.     forward[1] = forward[1] * 26;
  479.     VectorAdd(start, forward, start);
  480.     VectorCopy (self->enemy->s.origin, end);
  481.     end[2] += self->enemy->viewheight;
  482.     VectorSubtract (end, start, dir);
  483.  
  484.     gi.sound (self, CHAN_VOICE, sound_shoot, 1, ATTN_NORM, 0);
  485.     
  486.     VectorCopy (start, from);
  487.     tr = gi.trace (from, NULL, NULL, end, self, MASK_SHOT);      
  488.     VectorCopy (tr.endpos, from);
  489.         
  490.     gi.WriteByte (svc_temp_entity);
  491.     gi.WriteByte (TE_BLASTER_MUZZLEFLASH);
  492.     gi.WritePosition (start);
  493.     gi.multicast (start, MULTICAST_PHS);
  494.  
  495.     gi.WriteByte (svc_temp_entity);
  496.     gi.WriteByte (TE_BLASTERBEAM);
  497.     gi.WritePosition (start);
  498.     gi.WritePosition (end);
  499.     gi.multicast (start, MULTICAST_PHS); 
  500.     
  501.     if ((tr.ent != self) && (tr.ent->takedamage))
  502.         T_Damage (tr.ent, self, self, dir, tr.endpos, tr.plane.normal, damage, 0, 0, MOD_HYPERBLASTER);
  503.     else if (!((tr.surface) && (tr.surface->flags & SURF_SKY)))
  504.     {  
  505.         gi.WriteByte (svc_temp_entity);
  506.         gi.WriteByte (TE_SCREEN_SPARKS);
  507.         gi.WritePosition (tr.endpos);
  508.         gi.WriteDir (tr.plane.normal);
  509.         gi.multicast (self->s.origin, MULTICAST_PVS);
  510.     }
  511. }    
  512.  
  513. mframe_t soldier_frames_attack_shoot [] =
  514. {    
  515.     ai_charge, 0, NULL,
  516.     ai_charge, 0, NULL,
  517.     ai_charge, 0, NULL,
  518.     ai_charge, 0, Soldier_Shot,
  519.     ai_charge, 0, NULL,
  520.     ai_charge, 0, NULL,
  521.     ai_charge, 0, NULL,
  522.     ai_charge, 0, NULL,
  523.     ai_charge, 0, Soldier_Shot,
  524.     ai_charge, 0, NULL,
  525.     ai_charge, 0, NULL,
  526.     ai_charge, 0, NULL
  527. };
  528. mmove_t soldier_move_attack_shoot = {FRAME_shoot01, FRAME_shoot12, soldier_frames_attack_shoot, soldier_run};
  529.  
  530. mframe_t soldier_frames_attack_shoot2 [] =
  531. {    
  532.     ai_charge, 0, NULL,
  533.     ai_charge, 0, NULL,
  534.     ai_charge, 0, NULL,
  535.     ai_charge, 0, Soldier_Shot,
  536.     ai_charge, 0, NULL,
  537.     ai_charge, 0, NULL,
  538.     ai_charge, 0, NULL
  539. };
  540. mmove_t soldier_move_attack_shoot2 = {FRAME_shoot01, FRAME_shoot07, soldier_frames_attack_shoot2, soldier_run};
  541.  
  542. mframe_t soldier_frames_attack_shoot3 [] =
  543. {    
  544.     ai_charge, 0, NULL,
  545.     ai_charge, 0, NULL,
  546.     ai_charge, 0, NULL,
  547.     ai_charge, 0, Soldier_machgun,
  548.     ai_charge, 0, Soldier_machgun,
  549.     ai_charge, 0, Soldier_machgun,
  550.     ai_charge, 0, Soldier_machgun,
  551.     ai_charge, 0, Soldier_machgun,
  552.     ai_charge, 0, Soldier_machgun,
  553.     ai_charge, 0, NULL,
  554.     ai_charge, 0, NULL,
  555.     ai_charge, 0, NULL
  556. };
  557. mmove_t soldier_move_attack_shoot3 = {FRAME_shoot01, FRAME_shoot12, soldier_frames_attack_shoot3, soldier_run};
  558.  
  559. void soldier_attack (edict_t *self)
  560. {
  561.     if (random() < 0.5)
  562.         self->monsterinfo.currentmove = &soldier_move_attack_shoot;
  563.     else
  564.         self->monsterinfo.currentmove = &soldier_move_attack_shoot2;
  565. }
  566. void soldier_attack2 (edict_t *self)
  567. {
  568.     self->monsterinfo.currentmove = &soldier_move_attack_shoot3;
  569. }
  570. void commander_melee (edict_t *self)
  571. {
  572.     gi.sound (self, CHAN_VOICE, sound_ctalk, 1, ATTN_NORM, 0);
  573.     self->monsterinfo.currentmove = &soldier_move_comtalk;
  574. }
  575.  
  576. void soldier_melee (edict_t *self)
  577. {
  578.     if (self->spawnflags & 8)
  579.         self->monsterinfo.currentmove = & soldier_move_fall;
  580.     else
  581.         self->monsterinfo.currentmove = &soldier_move_talkstart;
  582. }
  583.  
  584. void soldier_talk (edict_t *self)
  585. {
  586.     if (self->spawnflags & 1)
  587.         self->monsterinfo.currentmove = &soldier_move_standstill;
  588.     else if(self->spawnflags & 8)
  589.         self->monsterinfo.currentmove = &soldier_move_fall;
  590.     else
  591.         self->monsterinfo.currentmove = &soldier_move_talk;
  592. }
  593.  
  594. mframe_t soldier_frames_pain [] =
  595. {
  596.     ai_move, 0, NULL,
  597.     ai_move, 0, NULL,
  598.     ai_move, 0, NULL,
  599.     ai_move, 0, NULL,
  600.     ai_move, 0, NULL,
  601.     ai_move, 0, NULL,
  602.     ai_move, 0, NULL
  603. };
  604. mmove_t soldier_move_pain = {FRAME_pain01, FRAME_pain07, soldier_frames_pain, soldier_run};
  605.  
  606. void soldier_pain (edict_t *self, edict_t *other, float kick, int damage)
  607. {
  608.     if (level.time < self->pain_debounce_time)
  609.         return;
  610.  
  611.     self->pain_debounce_time = level.time + 3;
  612.     gi.sound (self, CHAN_VOICE, sound_pain, 1, ATTN_NORM, 0);
  613.  
  614.     self->monsterinfo.currentmove = &soldier_move_pain;
  615. }
  616.  
  617. void soldier_duck_down (edict_t *self)
  618. {
  619.     if (self->monsterinfo.aiflags & AI_DUCKED)
  620.         return;
  621.  
  622.     self->monsterinfo.aiflags |= AI_DUCKED;
  623.     self->maxs[2] -= 32;
  624.     self->takedamage = DAMAGE_YES;
  625.     self->monsterinfo.pausetime = level.time + 1;
  626.     gi.linkentity (self);
  627. }
  628.  
  629. void soldier_duck_hold (edict_t *self)
  630. {
  631.     if (level.time >= self->monsterinfo.pausetime)
  632.         self->monsterinfo.aiflags &= ~AI_HOLD_FRAME;
  633.     else
  634.         self->monsterinfo.aiflags |= AI_HOLD_FRAME;
  635. }
  636.  
  637. void soldier_duck_up (edict_t *self)
  638. {
  639.     self->monsterinfo.aiflags &= ~AI_DUCKED;
  640.     self->maxs[2] += 32;
  641.     self->takedamage = DAMAGE_AIM;
  642.     gi.linkentity (self);
  643. }
  644.  
  645. mframe_t soldier_frames_duck [] =
  646. {
  647.     ai_move, 0, soldier_duck_down,
  648.     ai_move, 0, NULL,
  649.     ai_move, 0, soldier_duck_hold,
  650.     ai_move, 0, NULL,
  651.     ai_move, 0, soldier_duck_up,
  652.     ai_move, 0, NULL
  653. };
  654. mmove_t    soldier_move_duck = {FRAME_duck01, FRAME_duck05, soldier_frames_duck, soldier_run};
  655.  
  656. void soldier_dodge (edict_t *self, edict_t *attacker, float eta)
  657. {
  658.     if (random() > 0.5)
  659.         return;
  660.  
  661.     if (!self->enemy)
  662.         self->enemy = attacker;
  663.  
  664.     self->monsterinfo.currentmove = &soldier_move_duck;
  665. }
  666.  
  667. void soldier_dead (edict_t *self)
  668. {
  669.     VectorSet (self->mins, -16, -16, 0);
  670.     VectorSet (self->maxs, 16, 16, 24);
  671.     self->movetype = MOVETYPE_TOSS;
  672.     self->svflags |= SVF_DEADMONSTER;
  673.     self->nextthink = 0;
  674.     gi.linkentity (self);
  675. }
  676.  
  677.  
  678. mframe_t soldier_frames_death1 [] =
  679. {
  680.     ai_move, 0, NULL,
  681.     ai_move, 0, NULL,
  682.     ai_move, 0, NULL,
  683.     ai_move, 0, NULL,
  684.     ai_move, 0, NULL,
  685.     ai_move, 0, NULL,
  686.     ai_move, 0, NULL,
  687.     ai_move, 0, NULL,
  688.     ai_move, 0, NULL,
  689.     ai_move, 0, NULL,
  690.     ai_move, 0, NULL,
  691.     ai_move, 0, NULL,
  692.     ai_move, 0, NULL
  693.     
  694. };
  695. mmove_t soldier_move_death1 = {FRAME_die01, FRAME_die13, soldier_frames_death1, soldier_dead};
  696.  
  697.  
  698. mframe_t soldier_frames_death2 [] =
  699. {
  700.     ai_move, 0, NULL,
  701.     ai_move, 0, NULL,
  702.     ai_move, 0, NULL,
  703.     ai_move, 0, NULL,
  704.     ai_move, 0, NULL,
  705.     ai_move, 0, NULL,
  706.     ai_move, 0, NULL
  707. };
  708. mmove_t soldier_move_death2 = {FRAME_pain01, FRAME_pain07, soldier_frames_death2, soldier_dead};
  709.  
  710.  
  711. void soldier_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
  712. {
  713.     int        n;
  714.     vec3_t dir;
  715.     vec3_t normal;
  716.  
  717.     if (Q_stricmp(self->classname, "npc_soldier_hostile"))
  718.     {
  719.         if(self->spawnflags & 1)
  720.         {
  721.             if (inflictor->client)            // very very bad for these npc's to die!
  722.                 T_Damage (inflictor, self, self, dir, inflictor->s.origin,  normal, 200, 5, 0, 0);
  723.         }
  724.         else
  725.         {
  726.             if (inflictor->client)            // very bad to kill friendly npc's!!
  727.                 T_Damage (inflictor, self, self, dir, inflictor->s.origin,  normal, 20, 5, 0, 0);
  728.         }
  729.         if (self->deadflag == DEAD_DEAD)
  730.             return;
  731.     }
  732.  
  733.     if (self->health <= self->gib_health)
  734.     {
  735.         gi.sound (self, CHAN_VOICE, gi.soundindex ("misc/udeath.wav"), 1, ATTN_IDLE, 0);
  736.         for (n= 0; n < 2; n++)
  737.             ThrowGib (self, "models/objects/gibs/bone/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  738.         for (n= 0; n < 4; n++)
  739.             ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  740.         ThrowHead (self, "models/objects/gibs/head2/tris.md2", damage, GIB_ORGANIC, EF_GIB);
  741.         self->deadflag = DEAD_DEAD;
  742.     }
  743.  
  744.     gi.sound (self, CHAN_VOICE, sound_die, 1, ATTN_NORM, 0);
  745.     self->deadflag = DEAD_DEAD;
  746.     self->takedamage = DAMAGE_NO;
  747.  
  748.     self->monsterinfo.currentmove = &soldier_move_death1;
  749. }
  750.  
  751.  
  752. /*QUAKED monster_soldier (1 .5 0) (-16 -16 -24) (16 16 32) Ambush Trigger_Spawn Sight
  753. */
  754. void SP_npc_soldier (edict_t *self)
  755. {
  756.     if (deathmatch->value)
  757.     {
  758.         G_FreeEdict (self);
  759.         return;
  760.     }
  761.  
  762.     // pre-caches
  763.     sound_pain  = gi.soundindex ("soldier/pain.wav");
  764.     sound_die   = gi.soundindex ("soldier/death.wav");
  765.     sound_idle  = gi.soundindex ("soldier/breathe.wav");
  766.     sound_talk = gi.soundindex ("soldier/talk.wav");
  767.     sound_talk2 = gi.soundindex ("soldier/talk2.wav");
  768.     sound_search = gi.soundindex ("soldier/yell.wav");
  769.     sound_sight = gi.soundindex ("soldier/yell.wav");
  770.     sound_help = gi.soundindex ("soldier/help.wav");
  771.     sound_groan = gi.soundindex ("soldier/groan.wav");
  772.     sound_step1 = gi.soundindex ("player/step1.wav");
  773.     sound_step2 = gi.soundindex ("player/step2.wav");
  774.  
  775.         if(self->spawnflags & 1)
  776.     {
  777.  
  778.         self->s.modelindex = gi.modelindex("models/npc/hi_res/mach_gunner/tris.md2");
  779.  
  780.         self->s.modelindex2 = gi.modelindex("models/npc/mach_gun/tris.md2");
  781.     }
  782.     else
  783.         self->s.modelindex = gi.modelindex("models/npc/soldier/tris.md2");
  784.  
  785.     VectorSet (self->mins, -16, -16, 0);
  786.     VectorSet (self->maxs, 16, 16, 56);
  787.     self->movetype = MOVETYPE_STEP;
  788.     self->solid = SOLID_BBOX;
  789.  
  790.     self->classname = "npc_soldier";
  791.  
  792.     self->max_health = 150;
  793.     self->health = self->max_health;
  794.     self->gib_health = -40;
  795.     self->mass = 150;
  796.  
  797.     self->pain = NULL;        
  798.     self->die = soldier_die;
  799.     self->monsterinfo.stand = soldier_stand;
  800.     self->monsterinfo.walk = soldier_walk;
  801.     self->monsterinfo.run = soldier_run;
  802.     self->monsterinfo.dodge = NULL;
  803.     self->monsterinfo.attack = NULL;
  804.     self->monsterinfo.melee = soldier_melee;
  805.     self->monsterinfo.sight = soldier_sight;
  806.     self->monsterinfo.search = soldier_search;
  807.  
  808.     self->monsterinfo.currentmove = &soldier_move_stand;
  809.     self->monsterinfo.scale = MODEL_SCALE;
  810.     self->monsterinfo.aiflags = AI_NPC;
  811.  
  812.     gi.linkentity (self);
  813.  
  814.     walkmonster_start (self);
  815. }
  816.  
  817. void SP_npc_commander (edict_t *self)
  818. {
  819.     if (deathmatch->value)
  820.     {
  821.         G_FreeEdict (self);
  822.         return;
  823.     }
  824.  
  825.     // pre-caches
  826.     sound_pain  = gi.soundindex ("soldier/pain.wav");
  827.     sound_die   = gi.soundindex ("soldier/death.wav");
  828.     sound_idle  = gi.soundindex ("soldier/breathe.wav");
  829.     sound_ctalk = gi.soundindex ("commander/talk.wav");
  830.     sound_talk2 = gi.soundindex ("soldier/talk2.wav");
  831.     sound_search = gi.soundindex ("soldier/yell.wav");
  832.     sound_csight = gi.soundindex ("commander/yell.wav");
  833.     sound_help = gi.soundindex ("soldier/help.wav");
  834.     sound_groan = gi.soundindex ("soldier/groan.wav");
  835.     sound_step1 = gi.soundindex ("player/step1.wav");
  836.     sound_step2 = gi.soundindex ("player/step2.wav");
  837.  
  838.     self->s.modelindex = gi.modelindex("models/npc/commander/tris.md2");
  839.  
  840.     VectorSet (self->mins, -16, -16, 0);
  841.     VectorSet (self->maxs, 16, 16, 56);
  842.     self->movetype = MOVETYPE_STEP;
  843.     self->solid = SOLID_BBOX;
  844.  
  845.     self->classname = "npc_commander";
  846.  
  847.     self->max_health = 150;
  848.     self->health = self->max_health;
  849.     self->gib_health = 0;
  850.     self->mass = 150;
  851.  
  852.     self->pain = NULL;        
  853.     self->die = soldier_die;
  854.     self->monsterinfo.stand = soldier_stand;
  855.     self->monsterinfo.walk = soldier_stand;
  856.     self->monsterinfo.run = soldier_stand;
  857.     self->monsterinfo.dodge = NULL;
  858.     self->monsterinfo.attack = NULL;
  859.     self->monsterinfo.melee = commander_melee;
  860.     self->monsterinfo.sight = soldier_sight;
  861.     self->monsterinfo.search = soldier_search;
  862.  
  863.     self->monsterinfo.currentmove = &soldier_move_stand;
  864.     self->monsterinfo.scale = MODEL_SCALE;
  865.     self->monsterinfo.aiflags = AI_NPC;
  866.  
  867.     gi.linkentity (self);
  868.  
  869.     walkmonster_start (self);
  870. }
  871.  
  872. void SP_npc_soldier_standing (edict_t *self)
  873. {
  874.     if (deathmatch->value)
  875.     {
  876.         G_FreeEdict (self);
  877.         return;
  878.     }
  879.  
  880.     // pre-caches
  881.     sound_pain  = gi.soundindex ("soldier/pain.wav");
  882.     sound_die   = gi.soundindex ("soldier/death.wav");
  883.     sound_idle  = gi.soundindex ("soldier/breathe.wav");
  884.     sound_talk = gi.soundindex ("soldier/talk.wav");
  885.     sound_talk2 = gi.soundindex ("soldier/talk2.wav");
  886.     sound_search = gi.soundindex ("soldier/yell.wav");
  887.     sound_sight = gi.soundindex ("soldier/yell.wav");
  888.     sound_help = gi.soundindex ("soldier/help.wav");
  889.     sound_groan = gi.soundindex ("soldier/groan.wav");
  890.     sound_step1 = gi.soundindex ("player/step1.wav");
  891.     sound_step2 = gi.soundindex ("player/step2.wav");
  892.  
  893.     if(self->spawnflags & 4)
  894.     {
  895.  
  896.         self->s.modelindex = gi.modelindex("models/npc/hi_res/mach_gunner/tris.md2");
  897.  
  898.         self->s.modelindex2 = gi.modelindex("models/npc/mach_gun/tris.md2");
  899.     }
  900.     else
  901.         self->s.modelindex = gi.modelindex("models/npc/soldier/tris.md2");
  902.  
  903.     VectorSet (self->mins, -16, -16, 0);
  904.     VectorSet (self->maxs, 16, 16, 56);
  905.     self->movetype = MOVETYPE_STEP;
  906.     self->solid = SOLID_BBOX;
  907.  
  908.     self->classname = "npc_soldier";
  909.  
  910.     self->max_health = 150;
  911.     self->health = self->max_health;
  912.     self->gib_health = -40;
  913.     self->mass = 150;
  914.  
  915.     if (self->spawnflags & 1)
  916.     {
  917.         self->pain = soldier_pain;    
  918.         self->die = soldier_die;
  919.         self->monsterinfo.stand = soldier_stand;
  920.         self->monsterinfo.walk = soldier_walk;
  921.         self->monsterinfo.run = soldier_run;
  922.         self->monsterinfo.dodge = NULL;
  923.         self->monsterinfo.attack = soldier_run;
  924.         self->monsterinfo.melee = soldier_standby;
  925.         self->monsterinfo.sight = NULL;
  926.         self->monsterinfo.search = NULL;
  927.         self->monsterinfo.currentmove = &soldier_move_stand;
  928.     }
  929.     else
  930.     {
  931.         self->pain = soldier_pain;    
  932.         self->die = soldier_die;
  933.         self->monsterinfo.stand = soldier_standstill;
  934.         self->monsterinfo.walk = soldier_standstill;
  935.         self->monsterinfo.run = soldier_standstill;
  936.         self->monsterinfo.dodge = NULL;
  937.         self->monsterinfo.attack = NULL;
  938.         self->monsterinfo.melee = NULL;
  939.         self->monsterinfo.sight = NULL;
  940.         self->monsterinfo.search = NULL;
  941.         self->monsterinfo.currentmove = &soldier_move_standstill;
  942.     }
  943.     
  944.     self->monsterinfo.scale = MODEL_SCALE;
  945.     self->monsterinfo.aiflags = AI_NPC;
  946.  
  947.     gi.linkentity (self);
  948.  
  949.     walkmonster_start (self);
  950. }
  951.  
  952. void SP_npc_soldier_hostile (edict_t *self)
  953. {
  954.     if (deathmatch->value)
  955.     {
  956.         G_FreeEdict (self);
  957.         return;
  958.     }
  959.  
  960.     // pre-caches
  961.     sound_pain  = gi.soundindex ("soldier/pain.wav");
  962.     sound_die   = gi.soundindex ("soldier/death.wav");
  963.     sound_idle  = gi.soundindex ("soldier/breathe.wav");
  964.     sound_talk = gi.soundindex ("soldier/talk.wav");
  965.     sound_talk2 = gi.soundindex ("soldier/talk2.wav");
  966.     sound_search = gi.soundindex ("soldier/yell2.wav");
  967.     sound_sight = gi.soundindex ("soldier/yell2.wav");
  968.     sound_help = gi.soundindex ("soldier/help.wav");
  969.     sound_groan = gi.soundindex ("soldier/groan.wav");
  970.     sound_shoot2 = gi.soundindex ("weapons/machgf1b.wav");
  971.     sound_shoot = gi.soundindex ("weapons/blastf1a.wav");
  972.     sound_step1 = gi.soundindex ("player/step1.wav");
  973.     sound_step2 = gi.soundindex ("player/step2.wav");
  974.  
  975.     if (self->spawnflags & 4)
  976.     {
  977.  
  978.         self->s.modelindex = gi.modelindex("models/npc/hi_res/mach_gunner/tris.md2");
  979.  
  980.         self->s.modelindex2 = gi.modelindex("models/npc/mach_gun/tris.md2");
  981.     }
  982.     else
  983.         self->s.modelindex = gi.modelindex("models/npc/soldier/tris.md2");
  984.  
  985.     VectorSet (self->mins, -16, -16, 0);
  986.     VectorSet (self->maxs, 16, 16, 56);
  987.     self->movetype = MOVETYPE_STEP;
  988.     self->solid = SOLID_BBOX;
  989.  
  990.     self->classname = "npc_soldier_hostile";
  991.  
  992.     self->max_health = 150;
  993.     self->health = self->max_health;
  994.     self->gib_health = -40;
  995.     self->mass = 150;
  996.  
  997.     self->pain = soldier_pain; 
  998.     self->die = soldier_die;
  999.     self->monsterinfo.stand = soldier_stand;
  1000.     self->monsterinfo.walk = soldier_walk;
  1001.     self->monsterinfo.run = soldier_run;
  1002.     self->monsterinfo.dodge = soldier_dodge;
  1003.  
  1004.     if(self->spawnflags & 4)
  1005.     {
  1006.         self->monsterinfo.attack = soldier_attack2;
  1007.         self->monsterinfo.melee = soldier_attack2;
  1008.     }
  1009.     else
  1010.     {
  1011.         self->monsterinfo.attack = soldier_attack;
  1012.         self->monsterinfo.melee = soldier_attack;
  1013.     }
  1014.     self->monsterinfo.sight = soldier_sight;
  1015.     self->monsterinfo.search = soldier_search;
  1016.  
  1017.     self->monsterinfo.currentmove = &soldier_move_stand;
  1018.     self->monsterinfo.scale = MODEL_SCALE;
  1019.     self->monsterinfo.aiflags = AI_NPC;
  1020.  
  1021.     gi.linkentity (self);
  1022.  
  1023.     walkmonster_start (self);
  1024. }